昨天簡單的講了Props
,以及用Props
內的handleChange
舉了個例,相信大家對於“怎麼在React中使用TypeScript“,有多一點的認識。(我在開始寫文章前真的沒想到在React要使用TypeScript會這麼麻煩...)
今天,我們來看一下useEffect
,老實說其實滿簡單的,在一般人的認知,useEffect
就是拿來做"side effect"用的地方,side effect最常舉的例就是打api了。我們在元件渲染後,進到useEffect
函式內,執行第一個引數(一個callback,通常是拿來打api),再將api傳回來的資料寫進state當中,進而讓React幫我們更改DOM,完成新的畫面渲染。並根據第二個引數:一個控管變數的陣列(dependencies),來決定在什麼時機點要重新執行這個callback function。
我想這應該是大家的認知吧。不過你有想過React是怎麼定義這個useEffect
函式嗎?
讓我們在App.tsx內引入useEffect
吧:
//在App.tsx中
import { useEffect } from "react"
const App = () => {
//請幫我對useEffect按下右鍵,並選"移至定義"!
useEffect(()=>{},[])
return <div>Whatever</div>
}
對useEffect
按下"移至定義"後,我們會跑到"index.d.ts",也就是型別宣告檔內,裡面有React開發者對於useEffect
更詳盡的說明,超酷,而且超好懂。我沒有想過這個動作有這麼好用!
我們會看到下面這幾行
/**
* Accepts a function that contains imperative, possibly effectful code.
*
* @param effect Imperative function that can return a cleanup function
* @param deps If present, effect will only activate if the values in the list change.
*
* @version 16.8.0
* @see https://reactjs.org/docs/hooks-reference.html#useeffect
*/
function useEffect(effect: EffectCallback, deps?: DependencyList): void;
這邊已經明確說明了第一個參數(他取名叫effect)是個命令式的函式,可以回傳一個清理函式(cleanup function好像怎麼翻都怪)、第二個參數deps是一旦存在,就會在deps當中任何值有改變時,effect才會執行。並且除了這些說明外,你還能看到當初寫下這些文字時,React的版本在第幾版、以及相關的網址,讓你進行後續查找。(厲害package)的型別宣告檔通常都會包含這些資訊。
好,回到跟TypeScript有關的部分,看剛剛的最後一行:function useEffect(effect: EffectCallback, deps?: DependencyList): void;
effect
的型別是EffectCallback
,我們目前不知道他是什麼樣子,所以讓我們再對他執行一次"移至定義"吧!你會看到:
type EffectCallback = () => (void | Destructor);
啊哈,太好了,他就是一個函式,回傳值的型別是void(也就是不回傳任何值)或是Destructor
。Destructor
又是什麼呢?就是剛剛提到的清理函式啦,再移至定義吧:
type Destructor = () => void | { [UNDEFINED_VOID_ONLY]: never };
Destructor又是一個函式,回傳值的型別也是void,或者{ [UNDEFINED_VOID_ONLY]: never }
,這一行是用來表示,這個物件是絕不可能會被回傳的,如果你真的回傳了這種東西,那TypeScript就會報錯,讓你避開這個錯誤,同樣的作法我們也能用在絕不可能會被執行到的switch statement
。
然後,我們也來看一下選擇性的deps
的型別DependencyList
定義吧:
type DependencyList = ReadonlyArray<unknown>;
啊哈,我們知道這個陣列應該要是個唯讀陣列,且裡面的值是unknown
(不是any唷,其中差異可以再去翻閱之前的文章)。
最後,useEffect
回傳值的型別是void。
同樣的做法你也能對其他Hooks進行定義上的查詢,你會發現,裡面用到的字彙都不會太難!有沒有覺得特別有趣呢?我們只是透過TypeScript,既然能了解到更多useEffect
的實作知識呢!
useEffect
是個相對簡單,沒什麼陷阱跟意外的hook,明天我們再來看看其他hook跟TypeScript的關係跟用法吧!